﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BaseCardTypes = Wormhole.Engine.CardLibrary.BaseCardTypes;

namespace Wormhole.Engine.Input
{
	/// <author>Rodney McKay</author>
	/// <date>13 April 2008</date>
	/// <summary>
	/// This class is used to obtain input from the player.
	/// </summary>
	public class UserInput
	{
		#region Delegates
		/// <summary>
		/// This is the delegate for the Get Input event.
		/// </summary>
		/// <param name="request">The request details.</param>
		public delegate void GetInputDelegate(Request request);
		#endregion

		#region Events
		/// <summary>
		/// When input is required from the user this event is raised.
		/// </summary>
		public event GetInputDelegate GetInput;
		#endregion

		#region Properties

		#region Player
		/// <summary>
		/// The player the input is for.
		/// </summary>
		public Player.Player Player { get; set; }
		#endregion

		#region Callback
		/// <summary>
		/// This method is called when the user input has been received.
		/// </summary>
		protected Request.CallbackDelegate Callback { get; set; }
		#endregion

		#endregion

		#region Constructor
		/// <summary>
		/// Create a new user input object.
		/// </summary>
		/// <param name="player">The player the input is for.</param>
		public UserInput(Player.Player player)
		{
			this.Player = player;
		}
		#endregion

		#region On Get Input
		/// <summary>
		/// Rais the get input event.
		/// </summary>
		/// <param name="request">The request details.</param>
		private void OnGetInput(Request request)
		{
			if (this.GetInput != null)
				this.GetInput(request);
		}
		#endregion

		#region AskYesNo
		protected void AskYesNo(string message, Request.CallbackDelegate callback, Request.CallbackDelegate requestCallback)
		{
			this.Callback = callback;

			// create the request object
			Request request = new Request();
			request.Message = message;
			request.ResponseType = ResponseType.YesNo;
			request.Callback = requestCallback;

			// raise the get input event
			this.OnGetInput(request);
		}
		#endregion

		#region Keep Hand

		#region Keep Hand Input
		/// <summary>
		/// Ask the player whether or not the initial hand should be kept.
		/// </summary>
		public void KeepHandInput(Request.CallbackDelegate callback)
		{
			this.AskYesNo("Would you like to keep this hand?", callback, new Request.CallbackDelegate(this.KeepHandResult));
		}
		#endregion

		#region Keep Hand Result
		/// <summary>
		/// Process the user input.
		/// </summary>
		/// <param name="respons">The response values.</param>
		protected void KeepHandResult(Response response)
		{
			// call the callback function
			if (this.Callback != null)
				this.Callback(response);
		}
		#endregion

		#endregion

		#region Display Message
		/// <summary>
		/// Display a message to the user.
		/// </summary>
		/// <param name="message"></param>
		public void DisplayMessage(string message)
		{
			this.DisplayMessage(message, null);
		}

		/// <summary>
		/// Display a message to the user.
		/// </summary>
		/// <param name="message">The message to display.</param>
		public void DisplayMessage(string message, Decks.Deck cards)
		{
			this.Callback = null;

			// create the request object
			Request request = new Request();
			request.Message = message;
			request.ResponseType = ResponseType.None;

			// set the cards states to indicate which cards can be selected
			this.AllowSelect(cards);

			// raise the get input event
			this.OnGetInput(request);

		}
		#endregion

		#region Perform Action Input
		/// <summary>
		/// Prompt the user to perform an action.
		/// </summary>
		/// <param name="callback">The function to call when the input is received.</param>
		public void PerformActionInput(Request.CallbackDelegate callback)
		{
			this.Callback = callback;

			// create the request object
			Request request = new Request();
			request.Message = "Please select an action to perform.";
			request.ResponseType = ResponseType.Pass;

			if (this.Callback != null)
				request.Callback = new Request.CallbackDelegate(this.Callback);

			// raise the get input event
			this.OnGetInput(request);
		}
		#endregion

		#region Select Single Card Input
		public void SelectSingleCardInput(Request.CallbackDelegate callback, string message, Decks.Deck cards)
		{
			this.Callback = callback;

			// create the request object
			Request request = new Request();
			request.Message = message;
			request.ResponseType = ResponseType.SingleCardSelect;

			if (this.Callback != null)
				request.Callback = new Request.CallbackDelegate(this.Callback);

			// set the cards states to indicate which cards can be selected
			this.AllowSelect(cards);

			// raise the get input event
			this.OnGetInput(request);
		}
		#endregion

		#region Allow Select
		/// <summary>
		/// Highlight the cards that can be selected.
		/// </summary>
		/// <param name="cards">The collection of cards that can be selected.</param>
		protected void AllowSelect(Decks.Deck cards)
		{
			if (cards != null)
			{
				foreach (BaseCardTypes.Card card in this.Player.AllCards)
				{
					if (cards.Contains(card))
						card.InputStatus = BaseCardTypes.InputStatus.AllowSelect;
					else
						card.InputStatus = BaseCardTypes.InputStatus.Unavailable;
				}
			}
		}
		#endregion

		#region Play Another Mission

		#region PlayAnotherMissionInput
		/// <summary>
		/// Ask the player if he would like to play another mission.
		/// </summary>
		public void PlayAnotherMissionInput(Request.CallbackDelegate callback)
		{
			this.AskYesNo("Would you like to play another mission?", callback, new Request.CallbackDelegate(this.PlayAnotherMissionResult));
		}
		#endregion

		#region Play Another Mission Result
		/// <summary>
		/// Process the user input.
		/// </summary>
		/// <param name="respons">The response values.</param>
		protected void PlayAnotherMissionResult(Response response)
		{
			//if (response.ResponseType == ResponseType.No)
			//{
			//}

			// call the callback function
			if (this.Callback != null)
				this.Callback(response);
		}
		#endregion

		#endregion
	}
}
